// ----------------------------------------------------------------------------
// hash_fnv1a.h
// ----------------------------------------------------------------------------
#ifndef FW_BASE_HASH_FNV1A_H
#define FW_BASE_HASH_FNV1A_H
#include <fw/base/core/stdinteger.h>
#include <stddef.h>
#define FW_FNV1A_PRIME_32   (0x01000193)
#define FW_FNV1A_PRIME_64   (0x0000000100000001b3)

namespace fw
{
	namespace fnv1a
	{
		uint32_t		HashValueInternal32(const void* key, size_t len, uint32_t seed=0);
		uint64_t		HashValueInternal64(const void* key, size_t len, uint64_t seed=0);
        
        constexpr uint32_t  StaticHashValueLoop32(char c, const char* remain, size_t len, uint32_t value)
        {
            return len == 0 ? value : StaticHashValueLoop32(remain[0], remain+1, len-1, (value ^ c) * FW_FNV1A_PRIME_32);
        }
        
        constexpr uint64_t  StaticHashValueLoop64(char c, const char* remain, size_t len, uint64_t value)
        {
            return len == 0 ? value : StaticHashValueLoop64(remain[0], remain+1, len-1, (value ^ c) * FW_FNV1A_PRIME_64);
        }
        
        constexpr uint32_t  StaticHashValueInternal32(const char* key, size_t len, uint32_t seed)
        {
            return StaticHashValueLoop32(key[0], key+1, len-1, seed);
        }
        
        constexpr uint64_t  StaticHashValueInternal64(const char* key, size_t len, uint64_t seed)
        {
            return StaticHashValueLoop64(key[0], key+1, len-1, seed);
        }

        
	} // namespace fnv1a
} // namespace fw 

#endif // FW_BASE_HASH_FNV1A_H
